
#include <d3dcompiler.h>
#include <stdexcept>
#include <fstream>
#include "VertexShaderBinary.h"


VertexShaderBinary::VertexShaderBinary(const std::string& filepath)
{
	std::ifstream file(filepath); 
	if(!file)
		throw std::runtime_error("[Error] Opening file '" + filepath + "'failed!");

	std::string content((std::istreambuf_iterator<char>(file)), (std::istreambuf_iterator<char>()));

	ID3DBlob *shaderblob_out, *errors_out;
	HRESULT result = D3DCompile(content.c_str(),
								content.size(),
								NULL,
								NULL,
								NULL,
								"main",
								"vs_4_0",
								D3DCOMPILE_DEBUG,
								0,
								&shaderblob_out,
								&errors_out);

	m_ShaderBinary = make_com_ptr(shaderblob_out);
	com_ptr<ID3DBlob> errors = make_com_ptr(errors_out);

	if (FAILED(result))
	{			
		throw std::runtime_error("[Error] Compile shader '" + filepath + "' failed with error message: "
									+ static_cast<char*>(errors->GetBufferPointer()));
	}

}

com_ptr<ID3D11VertexShader> VertexShaderBinary::CreateShader(ID3D11Device* device)
{
	ID3D11VertexShader* shader_out;
	HRESULT hr = device->CreateVertexShader(m_ShaderBinary->GetBufferPointer(), m_ShaderBinary->GetBufferSize(), NULL, &shader_out);
	com_ptr<ID3D11VertexShader> shader = make_com_ptr(shader_out);

	if(FAILED(hr))
	{
		throw std::runtime_error("[Error] Create vertex shader failed!");
	}
	return shader;
}

com_ptr<ID3D11InputLayout> VertexShaderBinary::CreateInputLayout(ID3D11Device* device, D3D11_INPUT_ELEMENT_DESC layout[], int numElements)
{
	ID3D11InputLayout* inputlayout;
	HRESULT hr = device->CreateInputLayout(layout, numElements, m_ShaderBinary->GetBufferPointer(), m_ShaderBinary->GetBufferSize(), &inputlayout);

	if(FAILED(hr))
	{
		throw std::runtime_error("[Error] Create input layout failed!");
	}
	return make_com_ptr(inputlayout);
}